# -*- coding: utf-8 -*-
import os
import re
from contextlib import contextmanager
import requests
from urllib.parse import urlparse
import numpy as np

with open(os.path.join(os.path.dirname(__file__), "empty.png"), "rb") as empty_png_file:
    empty_png = empty_png_file.read()

R_18 = 152.87405657041106
R_10 = 39135.75848200009


def run_task(name, url, callback):
    host = urlparse(url).netloc
    for bbox in iter_bbox(*get_layer_bbox_origin(url)):
        with starting(name, bbox):
            content, bounds = layer_bbox_tile(name, bbox, host)
            if content and bounds:
                filename = os.path.join(name, "{}.png".format(bounds))
                callback(filename, content)


@contextmanager
def starting(layer, bbox):
    os.makedirs(".pending", exist_ok=True)
    if isinstance(bbox, str):
        filename = ".pending/{}.{}.pending".format(layer, bbox)
    else:
        filename = ".pending/{}.{}.pending".format(layer, bbox2string(bbox))
    open(filename, "w+").close()
    yield
    os.remove(filename)


def bbox2string(bbox):
    return ','.join(str(x) for x in bbox)


def string2bbox(string):
    return [float(x.strip()) for x in string.split(',')]


def layer_bbox_tile(layer, bbox, host):
    query = {
        'LAYERS': layer,
        'FORMAT': 'image/png',
        'SERVICE': 'WMS',
        'VERSION': '1.1.1',
        'REQUEST': 'GetMap',
        'EXCEPTIONS': 'application/vnd.ogc.se_inimage',
        'SRS': 'EPSG:3857',
        'BBOX': ','.join(str(x) for x in bbox),
        'WIDTH': '256',
        'HEIGHT': '256',
    }
    r = requests.get("http://{}/geowebcache/service/wms".format(host), params=query)
    r.raise_for_status()
    is_valid = 'geowebcache-tile-bounds' in r.headers and empty_png != r.content
    if is_valid:
        bounds = r.headers['geowebcache-tile-bounds']
        return r.content, bounds
    else:
        return None, None


def iter_bbox(bbox, origin, resolution=R_18):
    xmin, ymin, xmax, ymax = bbox
    ox, oy = origin
    xmin -= (xmin - ox) % resolution
    ymin -= (ymin - oy) % resolution
    for x in np.arange(xmin, xmax + resolution, resolution):
        for y in np.arange(ymin, ymax + resolution, resolution):
            yield x, y, x + resolution, y + resolution


def get_layer_bbox_origin(url):
    content = requests.get(url).content.decode()
    regexp = re.compile(r"map\.zoomToExtent\(new OpenLayers\.Bounds\(([0-9.\-,]+)\)")
    match = regexp.search(content)
    rv1 = [np.float64(x.strip()) for x in match.group(1).split(',')]
    assert len(rv1) == 4
    regexp = re.compile(r"new OpenLayers\.LonLat\(([0-9.\-\sEe,]+)\)")
    match = regexp.search(content)
    rv2 = [np.float64(x.strip()) for x in match.group(1).split(',')]
    assert len(rv2) == 2
    return rv1, rv2
